import { CsFundDouble } from '../common/csFundDouble.js';
import { FundAccount } from '../funds/fundAccount.js';
import { TargetObjFundingAccount } from '../funds/targetObjFundingAccount.js';
import {TransactionBalance} from '../funds/transactionBalacne.js';
import { Util } from '../../utils/util.js';

export const TargetObjectType = {
    TCustomer: { name: '客户', code: 0 },
    TSupplier: { name: '供应商', code: 1 },
    Unknown: { name: '未知往来单位', code: 2 },

    jsonToTargetType(value) {
        if (value == null) return this.Unknown;
        const index = Util.jsonToInt(value, -1);
        const types = [this.TCustomer, this.TSupplier, this.Unknown];
        if (index < 0 || index >= types.length - 1) return this.Unknown;
        return types[index];
    },

    values: ['TCustomer', 'TSupplier', 'Unknown']
};

// todo 更换
export const TargetObjectPlatformType = {
    TUserCreated: 0,
    TPlatformCreated: 1,
    Unknown: 2,
    All: 3,
    values: ['TUserCreated', 'TPlatformCreated', 'Unknown', 'All']
};

export class TargetObjectFilter {
    constructor({
        objName = null,
        contactPerson = null,
        phone = null,
        enable = null,
        code = null,
        objPlatformType = null,  //TargetObjectType
        excludedPlatformType = null,
        objType = null,
        mixedLikeInfo = null  // 混合查询
    } = {}) {
        this.objName = objName;
        this.contactPerson = contactPerson;
        this.phone = phone;
        this.enable = enable;
        this.code = code;
        this.objPlatformType = objPlatformType;  //TargetObjectType
        this.excludedPlatformType = excludedPlatformType;
        this.objType = objType;
        this.mixedLikeInfo = mixedLikeInfo;  // 混合查询
    }

    clear() {
        this.objName = null;
        this.contactPerson = null;
        this.phone = null;
        this.enable = null;
        this.code = null;
        this.mixedLikeInfo = null;
    }

    static clone(filter) {
        return new TargetObjectFilter({ ...filter });
    }

    cloneCopy(filter) {
        this.objName = filter.objName;
        this.contactPerson = filter.contactPerson;
        this.phone = filter.phone;
        this.enable = filter.enable;
        this.code = filter.code;
        this.objPlatformType = filter.objPlatformType;
        this.excludedPlatformType = filter.excludedPlatformType;
        this.objType = filter.objType;
        this.mixedLikeInfo = filter.mixedLikeInfo;
    }

    toJson() {
        const ret = {};
        if (this.objName) ret.lke_name = this.objName;
        if (this.contactPerson) ret.lke_contactUser = this.contactPerson;
        if (this.phone) ret.lke_contactPhone = this.phone;
        if (this.enable != null) ret.custState = this.enable ? 1 : 0;
        if (this.code) ret.lke_code = this.code;
        if (this.mixedLikeInfo) ret.ign_mixedLikeInfo = this.mixedLikeInfo;

        const t = TargetObjectPlatformType;
        if (this.objPlatformType != null) {
            switch (this.objPlatformType) {
                case t.Unknown:
                    break;
                case t.All:
                    ret.neq_platformCustomer = t.All;
                    break;
                case t.TUserCreated:
                    ret.neq_platformCustomer = t.TPlatformCreated;
                    break;
                case t.TPlatformCreated:
                    ret.neq_platformCustomer = t.TUserCreated;
                    break;
            }
        }

        if (
            this.excludedPlatformType &&
            this.excludedPlatformType !== TargetObjectType.Unknown
        ) {
            ret.ign_excludedPlatformTargetObj = this.excludedPlatformType.code;
        }

        if (this.objType != null) {
            ret.customerType = this.objType.code;
        }

        return ret;
    }
}

export class TargetObject {
    constructor({
        id = '',
        name = '',
        objType,
        contactName = '',
        contactPhoneNumber = '',
        email = '',
        city = '',
        address = '',
        remark = '',
        code = '',
        platformType = TargetObjectPlatformType.TUserCreated,
        fundAccountList = [], // 账户列表 是从每次交易中增减得到的金额
        // metalBalances 和 fundAccountList 实际是类似的东西，只是metalBalances 是从记录中汇聚出来。
        // 部分商户业务关注最近汇聚信息的，采用该模式
        transactionBalacnes = [],    // 类型 TransactionBalance
        initFundValue = null,
        enabled = true,
        quickExtentionFields = {}, // 快速非关联外扩
        extentionFields = {},  // 普通非关联外扩

    }) {
        this.id = id;
        this.name = name;
        this.code = code;
        this.contactName = contactName;
        this.contactPhoneNumber = contactPhoneNumber;
        this.email = email;
        this.city = city;
        this.address = address;
        this.remark = remark;
        this.objType = objType;
        this.platformType = platformType;
        this.fundAccount = fundAccountList.map(f => new FundAccount(f));
        this.transactionBalacnes = transactionBalacnes;
        this._initFundValue = initFundValue != null ? new CsFundDouble(initFundValue) : null;
        this.fundAmount = CsFundDouble.zero();
        this.receiveInfo = null;
        this.paymentInfo = null;
        this.preReceive = null;
        this.prePayment = null;
        this.enabled = enabled;  // 是否启用
        this.quickExtentionFields = quickExtentionFields;
        this.extentionFields = extentionFields;
    }

    static clone(obj) {
        const newObj = new TargetObject({
            id: obj.id,
            name: obj.name,
            objType: obj.objType,
            contactName: obj.contactName,
            contactPhoneNumber: obj.contactPhoneNumber,
            email: obj.email,
            city: obj.city,
            address: obj.address,
            remark: obj.remark,
            code: obj.code,
            platformType: obj.platformType,
            fundAccountList: obj.fundAccount,
            enabled: obj.enabled,
            quickExtentionFields: obj.quickExtentionFields,
            extentionFields: obj.extentionFields,
        });
        newObj.receiveInfo = obj.receiveInfo;
        newObj.paymentInfo = obj.paymentInfo;
        newObj.preReceive = obj.preReceive;
        newObj.prePayment = obj.prePayment;
        newObj._initFundValue = obj._initFundValue;
        newObj.fundAmount = obj.fundAmount;
        return newObj;
    }

    // todo 是否删除 ？
    cloneCopy(obj) {
        this.id = obj.id;
        this.name = obj.name;
        this.objType = obj.objType;
        this.contactName = obj.contactName;
        this.contactPhoneNumber = obj.contactPhoneNumber;
        this.email = obj.email;
        this.city = obj.city;
        this.address = obj.address;
        this.remark = obj.remark;
        this.code = obj.code;
        this.platformType = obj.platformType;
        this.fundAccount = obj.fundAccount.map(f => FundAccount.clone(f));

        this._initFundValue = obj._initFundValue;
        this.fundAmount = obj.fundAmount;
        this.receiveInfo = obj.receiveInfo;  // TargetObjFundingAccount
        this.paymentInfo = obj.paymentInfo;  // TargetObjFundingAccount
        this.preReceive = obj.preReceive;
        this.prePayment = obj.prePayment;
        this.enabled = obj.enabled;  // 是否启用
    }

    get initFundValue() {
        if (!this._initFundValue) this._initFundValue = CsFundDouble.zero();
        return this._initFundValue;
    }

    set initFundValue(value) {
        this._initFundValue = value;
    }

    static jsonToTargetObjectPlatformType(value, defaultValue = TargetObjectPlatformType.Unknown) {
        if (value == null) return defaultValue;
        try {
            return TargetObjectPlatformType.values[value] != null ? value : defaultValue;
        } catch (err) {
            console.log(`Convert jsonToTargetObjectPlatformType failed: ${err}`);
            return defaultValue;
        }
    }

    equal(obj) {
        return (
            this.name === obj.name &&
            this.contactName === obj.contactName &&
            this.contactPhoneNumber === obj.contactPhoneNumber &&
            this.email === obj.email &&
            this.city === obj.city &&
            this.address === obj.address &&
            this.remark === obj.remark &&
            this.code === obj.code
        );
    }

    /**
 * Creates an empty TargetObject with default values
 * @param {object} params - Parameters object
 * @param {TargetObjectType} params.objType - The type of target object
 * @param {number} [params.initFundValue] - Initial fund value (optional)
 * @returns {TargetObject} New empty TargetObject instance
 */
    static empty({ objType , initFundValue  }={}) {
        return new TargetObject({
            id: "",
            name: "",
            objType: objType || TargetObjectType.TCustomer,
            contactName: "",
            contactPhoneNumber: "",
            email: "",
            city: "",
            address: "",
            remark: "",
            code: "",
            platformType: TargetObjectPlatformType.TUserCreated,
            fundAccountList: [],
            initFundValue: initFundValue,
            // These will be initialized by the constructor:
            // fundAmount: CsFundDouble.zero(),
            // receiveInfo: null,
            // paymentInfo: null,
            // preReceive: null,
            // prePayment: null
        });
    }

    static fromJsonForOrders(json, type = null) {
        const obj = new TargetObject({
            id: Util.jsonToString(json.objId),
            code: Util.jsonToString(json.objCode),
            name: Util.jsonToString(json.objName),
            contactName: Util.jsonToString(json.objContactUser),
            contactPhoneNumber: Util.jsonToString(json.objContactPhone),
            email: Util.jsonToString(json.objContactEmail),
            city: Util.jsonToString(json.objCity),
            address: Util.jsonToString(json.objDetailAddr),
            remark: Util.jsonToString(json.objRemark),
            objType: type || TargetObjectType.jsonToTargetType(json.objCustomerType)
        });
        obj.preReceive = Util.jsonToCsFundDouble(json.objPreReceiveBalance, 0);
        obj.prePayment = Util.jsonToCsFundDouble(json.objPrePaymentBalance, 0);
        obj.platformType = TargetObject.jsonToTargetObjectPlatformType(json.objIsPlatformCustomer);
        obj.fundAmount = Util.jsonToCsFundDouble(json.objFundBalance, 0); // 注意与fromJson 不一样
        return obj;
    }

    static fromJson(json, type = null) {
        const obj = new TargetObject({
            id: Util.jsonToString(json.id),
            code: Util.jsonToString(json.code),
            name: Util.jsonToString(json.name),
            contactName: Util.jsonToString(json.contactUser),
            contactPhoneNumber: Util.jsonToString(json.contactPhone),
            email: Util.jsonToString(json.contactEmail),
            city: Util.jsonToString(json.city),
            address: Util.jsonToString(json.detailAddr),
            remark: Util.jsonToString(json.remark),
            objType: type || TargetObjectType.jsonToTargetType(json.customerType),
            enabled: Util.jsonToBool(json.custState, true), 
            quickExtentionFields: Util.jsonStringToJson(json.quickExtentionFields),
            extentionFields: Util.jsonStringToJson(json.extentionFields),           
        });

        obj.receiveInfo = TargetObjFundingAccount.fromJson(json.waitReceiptInfo || {});
        obj.paymentInfo = TargetObjFundingAccount.fromJson(json.waitPaymentInfo || {});
        obj.receiveInfo.tObj = obj;
        obj.paymentInfo.tObj = obj;

        obj.platformType = TargetObject.jsonToTargetObjectPlatformType(json.isPlatformCustomer);
        obj.preReceive = Util.jsonToCsFundDouble(json.preReceive, 0);
        obj.prePayment = Util.jsonToCsFundDouble(json.prePayment, 0);
        obj._initFundValue = Util.jsonToCsFundDouble(json._initFundValue, 0);
        obj.fundAmount = Util.jsonToCsFundDouble(json.debtAmount, 0);
              
        const list = json.fundAccountDetails || [];
        for (const e of list) {
            obj.fundAccount.push(FundAccount.fromJson(e));
        }

        return obj;
    }

        static fromJson_ForTrasitionBalance(json, type = null) {
        const obj = new TargetObject({
            id: Util.jsonToString(json.id),
            code: Util.jsonToString(json.code),
            name: Util.jsonToString(json.name),
            contactName: Util.jsonToString(json.contactUser),
            contactPhoneNumber: Util.jsonToString(json.contactPhone),
            email: Util.jsonToString(json.contactEmail),
            city: Util.jsonToString(json.city),
            address: Util.jsonToString(json.detailAddr),
            remark: Util.jsonToString(json.remark),
            objType: type || TargetObjectType.jsonToTargetType(json.customerType),
            enabled: Util.jsonToBool(json.custState, true)
        });

        obj.fundAmount = Util.jsonToCsFundDouble(json.debtAmount, 0);
        obj.platformType = TargetObject.jsonToTargetObjectPlatformType(json.isPlatformCustomer);
      

        const list = json.pirodBalances || [];
        for (const e of list) {
            obj.transactionBalacnes.push(TransactionBalance.fromJson(e));
        }

        return obj;
    }

    toPrintInfoJson() {
        return {
            id: this.id,
            code: this.code,
            name: this.name,
            contactName: this.contactName,
            contactPhoneNumber: this.contactPhoneNumber,
            email: this.email,
            city: this.city,
            address: this.address,
            remark: this.remark,
            objType: this.objType
        };
    }
}
